﻿using System;
using System.Windows.Forms;
using SlimDX;

namespace Editor
{
    partial class EditorWindow
    {
        private void SceneView_MouseDown(object sender, MouseEventArgs e)
        {
            m_ViewMouseDownLocation = e.Location;
            m_ViewMouseCurrentLocation = e.Location;
            ActiveView = sender as DirectXView;
            m_ViewMouseDown = true;

            if (m_KeyShiftDown)
            {
                m_SelectedEntities = ActiveView.GetEntitiesAtPoint(e.Location);
            }
        }

        private void SceneView_MouseUp(object sender, MouseEventArgs e)
        {
            m_ViewMouseDown = false;

            if (m_ViewDragging)
            {
                ActiveView.Capture = false;

                m_ViewDragging = false;
                m_DragType = DragType.None;

                if (m_CurrentCommand != null)
                {
                    m_CurrentCommand.Undo();
                    m_Document.CommandManager.Do(m_CurrentCommand);
                    m_CurrentCommand = null;
                }
            }
        }

        private void SceneView_MouseMove(object sender, MouseEventArgs e)
        {
            if (m_ViewMouseDown && (ActiveView != null) && !m_ViewDragging && (m_DragType == DragType.None) &&
                ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Right)))
            {
                if (e.Location != m_ViewMouseDownLocation)
                {
                    ActiveView.Capture = true;

                    m_ViewDragging = true;

                    if (e.Button == MouseButtons.Left)
                    {
                        if (m_KeyCtrlDown && m_KeyAltDown)
                        {
                            m_DragType = DragType.RotateCameraAboutCamera;
                        }
                        else if (m_KeyCtrlDown)
                        {
                            m_DragType = DragType.RotateCameraAboutTarget;
                        }
                        else
                        {
                            if (m_EditType == EditType.Move)
                            {
                                m_DragType = DragType.TranslateObject;
                            }
                            else if (m_EditType == EditType.Rotate)
                            {
                                m_DragType = DragType.RotateObject;
                            }
                        }
                    }
                    else if (e.Button == MouseButtons.Right)
                    {
                        if (m_KeyCtrlDown)
                        {
                            m_DragType = DragType.TranslateCamera;
                        }
                    }
                }
            }

            if (m_ViewMouseDown && m_ViewDragging && (m_DragType != DragType.None))
            {
                float deltaX = ((float)(e.Location.X - m_ViewMouseCurrentLocation.X)) / 100.0f;
                float deltaY = ((float)(e.Location.Y - m_ViewMouseCurrentLocation.Y)) / 100.0f;

                if (m_DragType == DragType.RotateObject)
                {
                    Command.ICommand newCommand = m_Document.RotateEntities(m_SelectedEntities, deltaX, deltaY, 0.0f, Matrix.Invert(ActiveView.Camera.Transform));
                    if (m_CurrentCommand != null)
                    {
                        m_CurrentCommand.Undo();
                        m_CurrentCommand.Merge(newCommand);
                    }
                    else
                    {
                        m_CurrentCommand = newCommand;
                    }
                    m_CurrentCommand.Do();
                }
                else if (m_DragType == DragType.TranslateObject)
                {
                    float scale = Math.Max(1.0f, ActiveView.Camera.CurrentDistance / 10.0f);
                    Command.ICommand newCommand = m_Document.MoveEntities(m_SelectedEntities, deltaX * scale, -deltaY * scale, 0.0f, Matrix.Invert(ActiveView.Camera.Transform));
                    if (m_CurrentCommand != null)
                    {
                        m_CurrentCommand.Undo();
                        m_CurrentCommand.Merge(newCommand);
                    }
                    else
                    {
                        m_CurrentCommand = newCommand;
                    }
                    m_CurrentCommand.Do();
                }
                else if (m_DragType == DragType.RotateCameraAboutCamera)
                {
                    ActiveView.RotateCamera(Camera.RotateType.AboutCamera, deltaY, deltaX);
                }
                else if (m_DragType == DragType.RotateCameraAboutTarget)
                {
                    ActiveView.RotateCamera(Camera.RotateType.AboutTarget, -deltaY, -deltaX);
                }
                else if (m_DragType == DragType.TranslateCamera)
                {
                    ActiveView.MoveCamera(new Vector3(-deltaX, deltaY, 0));
                }

                m_ViewMouseCurrentLocation = e.Location;
            }
        }

        private void SceneView_MouseWheel(object sender, MouseEventArgs e)
        {
            if (m_KeyCtrlDown)
            {
                if (m_KeyAltDown)
                {
                    ActiveView.MoveCamera(new Vector3(0, 0, (float)e.Delta / 100.0f));
                }
                else
                {
                    ActiveView.ZoomCamera((float)e.Delta);
                }
            }
        }

        private void SceneView_KeyDown(object sender, KeyEventArgs e)
        {
            m_KeyCtrlDown = e.Control;
            m_KeyAltDown = e.Alt;
            m_KeyShiftDown = e.Shift;

            if (m_ViewDragging)
            {
                if (e.KeyCode == Keys.Escape)
                {
                    ActiveView.Capture = false;

                    m_ViewDragging = false;
                    m_ViewMouseDown = false;
                    m_DragType = DragType.None;

                    if (m_CurrentCommand != null)
                    {
                        m_CurrentCommand.Undo();
                        m_CurrentCommand = null;
                    }

                    e.Handled = true;
                    e.SuppressKeyPress = true;
                }
            }
            else if (e.KeyCode == Keys.F)
            {
                ActiveView.FocusCamera(m_SelectedEntities);
                e.Handled = true;
                e.SuppressKeyPress = true;
            }
            else if (e.KeyCode == Keys.Q)
            {
                m_EditType = EditType.Select;
                UpdateEditTypeButtons();
                e.Handled = true;
                e.SuppressKeyPress = true;
            }
            else if (e.KeyCode == Keys.W)
            {
                m_EditType = EditType.Move;
                UpdateEditTypeButtons();
                e.Handled = true;
                e.SuppressKeyPress = true;
            }
            else if (e.KeyCode == Keys.E)
            {
                m_EditType = EditType.Rotate;
                UpdateEditTypeButtons();
                e.Handled = true;
                e.SuppressKeyPress = true;
            }
            else if (e.KeyCode == Keys.R)
            {
                m_EditType = EditType.Scale;
                UpdateEditTypeButtons();
                e.Handled = true;
                e.SuppressKeyPress = true;
            }
			else if (ActiveEditMode != null)
			{
				ActiveEditMode.OnKeyDown(e);
			}
        }

        private void SceneView_KeyUp(object sender, KeyEventArgs e)
        {
            m_KeyCtrlDown = e.Control;
            m_KeyAltDown = e.Alt;
            m_KeyShiftDown = e.Shift;

			if (ActiveEditMode != null)
			{
				ActiveEditMode.OnKeyUp(e);
			}
        }
    }
}
